package com.lw.leetcode.sort.b;

import java.util.Map;
import java.util.TreeMap;

/**
 * Created with IntelliJ IDEA.
 * 731. 我的日程安排表 II
 *
 * @author liw
 * @version 1.0
 * @date 2022/6/7 17:14
 */
public class MyCalendarTwo {

    public static void main(String[] args) {
        MyCalendarTwo test = new MyCalendarTwo();


        //[null, 1, 1, 2, 3, 3, 3]
//        System.out.println(test.book(10, 20));
//        test.aa();
//        System.out.println(test.book(50, 60));
//        test.aa();
//        System.out.println(test.book(10, 40));
//        test.aa();
//        System.out.println(test.book(5, 15));
//        test.aa();
//        System.out.println(test.book(5, 10));
//        test.aa();
//        System.out.println(test.book(25, 55));
//        test.aa();

        // [null,1,1,1,1,1,2,2,2,3,3,3,4,5,5,5,5,5,5,6,6,6,6,6,6,7,7,7,7,7,7]
        System.out.println(test.book(47, 50));
        test.aa();
        System.out.println(test.book(1, 10));
        test.aa();
        System.out.println(test.book(27, 36));
        test.aa();
        System.out.println(test.book(40, 47));
        test.aa();
        System.out.println(test.book(20, 27));
        test.aa();
        System.out.println(test.book(15, 23));
        test.aa();
        System.out.println(test.book(10, 18));
        test.aa();
        System.out.println(test.book(27, 36));
        test.aa();
        System.out.println(test.book(17, 25));
        test.aa();
        System.out.println(test.book(8, 17));
        test.aa();
        System.out.println(test.book(24, 33));
        test.aa();
        System.out.println(test.book(23, 28));
        test.aa();
        System.out.println(test.book(21, 27));
        test.aa();
        System.out.println(test.book(47, 50));
        test.aa();
        System.out.println(test.book(14, 21));
        test.aa();
        System.out.println(test.book(26, 32));
        test.aa();
        System.out.println(test.book(16, 21));
        test.aa();
        System.out.println(test.book(2, 7));
        test.aa();
        System.out.println(test.book(24, 33));
        test.aa();
        System.out.println(test.book(6, 13));
        test.aa();
        System.out.println(test.book(44, 50));
        test.aa();
        System.out.println(test.book(33, 39));
        test.aa();
        System.out.println(test.book(30, 36));
        test.aa();
        System.out.println(test.book(6, 15));
        test.aa();
        System.out.println(test.book(21, 27));
        test.aa();
        System.out.println(test.book(49, 50));
        test.aa();
        System.out.println(test.book(38, 45));
        test.aa();
        System.out.println(test.book(4, 12));
        test.aa();
        System.out.println(test.book(46, 50));
        test.aa();
        System.out.println(test.book(13, 21));
        test.aa();

//        System.out.println(test.book(1, 2));
//        test.aa();
//        System.out.println(test.book(1, 2));
//        test.aa();
    }

    private void aa() {
        for (Map.Entry<Integer, Long> entry : map.entrySet()) {
            long value = entry.getValue();
            int e = (int) (value >> 32);
            int c = (int) value;
            System.out.println(entry.getKey() + "   " + e + "   " + c);
        }
    }


    private TreeMap<Integer, Long> map;

    public MyCalendarTwo() {
        map = new TreeMap<>();
    }

    public boolean book(int start, int end) {

        if (!check(start, end)) {
            return false;
        }

        Map.Entry<Integer, Long> floor = map.floorEntry(start);
        if (floor != null) {
            long value = floor.getValue();
            int e = (int) (value >> 32);
            int c = (int) value;
            if (e >= end) {
                map.put(floor.getKey(), ((long) start << 32) + c);
                if (end != e) {
                    map.put(end, value);
                }
                map.put(start, ((long) end << 32) + c + 1);
                start = e;
            } else if (e > start) {
                map.put(floor.getKey(), ((long) start << 32) + c);
                map.put(start, value + 1);
                start = e;
            }
        }
        Map.Entry<Integer, Long> ceiling = map.ceilingEntry(start);
        while (ceiling != null && ceiling.getKey() < end) {
            long value = ceiling.getValue();
            int e = (int) (value >> 32);
            int c = (int) value;
            int key = ceiling.getKey();

            if (start < key) {
                map.put(start, ((long) key << 32) + 1);
                start = key;
            } else {
                if (end < e) {
                    map.put(start, ((long) end << 32) + c + 1);
                    map.put(end, value);
                } else {
                    map.put(start, value + 1);
                }
                start = e;
            }
            ceiling = map.ceilingEntry(start);
        }
        if (start < end) {
            map.put(start, ((long) end << 32) + 1);
        }
        return true;
    }


    public boolean check(int start, int end) {
        Map.Entry<Integer, Long> floor = map.floorEntry(start);
        if (floor != null) {
            long value = floor.getValue();
            int e = (int) (value >> 32);
            int c = (int) value;
            if (e > start) {
                if (c > 1) {
                    return false;
                }
                start = e;
            }
        }
        Map.Entry<Integer, Long> ceiling = map.ceilingEntry(start);
        while (ceiling != null && ceiling.getKey() < end) {
            long value = ceiling.getValue();
            int e = (int) (value >> 32);
            int c = (int) value;
            if (c > 1) {
                return false;
            }
            start = e;
            ceiling = map.ceilingEntry(start);
        }
        return true;
    }

}
